package com.dlc.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dlc.shop.bean.dto.StockPointSkuDTO;
import com.dlc.shop.bean.enums.StockModeEnum;
import com.dlc.shop.bean.model.Station;
import com.dlc.shop.bean.model.StockPointSku;
import com.dlc.shop.bean.model.Warehouse;
import com.dlc.shop.bean.vo.SkuStockVO;
import com.dlc.shop.bean.vo.StationVO;
import com.dlc.shop.bean.vo.StockPointSkuVO;
import com.dlc.shop.bean.vo.WarehouseVO;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.constants.StockPointType;
import com.dlc.shop.common.enums.SysTypeEnum;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.util.BeanUtil;
import com.dlc.shop.common.util.PageParam;
import com.dlc.shop.dao.StationMapper;
import com.dlc.shop.dao.StockPointSkuMapper;
import com.dlc.shop.dao.WarehouseMapper;
import com.dlc.shop.manager.impl.StockManager;
import com.dlc.shop.service.StockPointSkuService;
import com.dlc.shop.util.StockUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author FrozenWatermelon
 * @date 2023-11-09 18:00:43
 */
@Service
@AllArgsConstructor
public class StockPointSkuServiceImpl extends ServiceImpl<StockPointSkuMapper, StockPointSku> implements StockPointSkuService {

    private final StockPointSkuMapper stockPointSkuMapper;
    private final WarehouseMapper warehouseMapper;
    private final StationMapper stationMapper;
    private final StockManager stockManager;

    @Override
    public IPage<StockPointSku> page(PageParam pageDTO) {
        return stockPointSkuMapper.list(pageDTO);
    }

    @Override
    public StockPointSku getByStockPointSkuId(Long stockPointSkuId) {
        return stockPointSkuMapper.getByStockPointSkuId(stockPointSkuId);
    }

    @Override
    public void insert(StockPointSku stockPointSku) {
        stockPointSku.setType(Objects.isNull(stockPointSku.getType()) ? 1 : stockPointSku.getType());
        stockPointSkuMapper.save(stockPointSku);
    }

    @Override
    public void update(StockPointSku stockPointSku) {
        stockPointSkuMapper.update(stockPointSku);
    }

    @Override
    public void deleteById(Long stockPointSkuId) {
        stockPointSkuMapper.deleteById(stockPointSkuId);
    }

    @Override
    public void deleteByIds(List<Long> stockPointSkuIds) {
        if (CollectionUtils.isEmpty(stockPointSkuIds)) {
            return;
        }
        stockPointSkuMapper.deleteByIds(stockPointSkuIds);
    }

    @Override
    public void deleteBySpuId(Long prodId) {
        stockPointSkuMapper.deleteBySpuId(prodId);
    }

    @Override
    public void batchDeleteByStockPointSkuIdList(List<Long> stockPointSkuIdList) {
        if (CollectionUtil.isEmpty(stockPointSkuIdList)) {
            return;
        }
        stockPointSkuMapper.batchDeleteByStockPointSkuIdList(stockPointSkuIdList);
    }

    @Override
    public boolean batchSave(List<StockPointSkuDTO> stockPointDTOList) {
        if (CollectionUtil.isEmpty(stockPointDTOList)) {
            return Boolean.TRUE;
        }
//        if (CollectionUtil.isEmpty(stockPointDTOList)) {
//            throw new LuckException("库存不能为空");
//        }
        Set<Long> warehouseIdList = new HashSet<>();
        Set<Long> stationIdList = new HashSet<>();
        for (StockPointSkuDTO stockPointSkuDTO : stockPointDTOList) {
            stockPointSkuDTO.setType(Objects.isNull(stockPointSkuDTO.getType()) ? 1 : stockPointSkuDTO.getType());
            if (stockPointSkuDTO.getStockPointType() == StockPointType.STATION.getValue()) {
                stationIdList.add(stockPointSkuDTO.getStockPointId());
            }
            warehouseIdList.add(stockPointSkuDTO.getStockPointId());
        }
        // 判断门店和仓库是否被删除
        if (!warehouseIdList.isEmpty()) {
            if (warehouseMapper.selectCount(new LambdaQueryWrapper<>(Warehouse.class).in(Warehouse::getWarehouseId, warehouseIdList)) != warehouseIdList.size()) {
                throw new YamiShopBindException("yami.stock.point.error");
            };
        }
        if (!stationIdList.isEmpty()) {
            List<Station> stationList = stationMapper.selectList(new LambdaQueryWrapper<>(Station.class).in(Station::getStationId, stationIdList).ne(Station::getStatus, -1));
            if (stationList.size() != stationIdList.size()) {
                throw new YamiShopBindException("yami.stock.point.error");
            };
            Map<Long, Integer> stationMap = stationList.stream().collect(Collectors.toMap(Station::getStationId, Station::getStockMode));
            stockPointDTOList.forEach(s-> {
                if (Objects.equals(stationMap.get(s.getStockPointId()), StockModeEnum.ALL_STOCK.value())) {
                    throw new YamiShopBindException("yami.stock.point.error");
                }
            });
        }
        stockPointSkuMapper.batchSave(stockPointDTOList);
        return Boolean.TRUE;
    }

    @Override
    public List<StockPointSkuVO> listBySkuIds(List<Long> skuIds) {
        return stockPointSkuMapper.listBySkuIds(skuIds);
    }

    @Override
    public List<StockPointSkuVO> listPointIdsBySkuIds(List<Long> skuIds) {
        List<StockPointSkuVO> stockPoints = stockPointSkuMapper.listBySkuIds(skuIds);
        return stockPoints;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeStockPoint(List<StockPointSkuDTO> stockPointDTOList, boolean isUpdate) {
        // 获取商品原来的关联数据
        List<Long> skuIds = stockPointDTOList.stream().map(StockPointSkuDTO::getSkuId).collect(Collectors.toList());
        List<StockPointSkuVO> stockPointSkuDb = stockPointSkuMapper.listBySkuIds(skuIds);
        Map<String, List<StockPointSkuVO>> pointMap = stockPointSkuDb.stream().collect(Collectors.groupingBy(stockPoint -> stockPoint.getStockPointId() + "_" + stockPoint.getSkuId()));
        // 需要添加的新库存点数据
        List<StockPointSkuDTO> insertSkuList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 需要删除的关联库存点
        List<Long> deleteSkuIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 需要修改的数据
        List<StockPointSkuDTO> updateSkuList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 转换成插入的数据
        Map<Long, List<StockPointSkuDTO>> skuStockMap = stockPointDTOList.stream().collect(Collectors.groupingBy(StockPointSkuDTO::getSkuId));

        for (StockPointSkuDTO stockPointSku : stockPointDTOList) {
            String key = stockPointSku.getStockPointId() + "_" + stockPointSku.getSkuId();
            if (pointMap.containsKey(key)) {
                List<StockPointSkuVO> pointSkuVOS = pointMap.get(key);
                for (StockPointSkuVO pointSkuVO : pointSkuVOS) {
                    if (stockPointSku.getStock() == 0 && !Objects.equals(pointSkuVO.getType(), 0)) {
                        deleteSkuIds.add(pointSkuVO.getStockPointSkuId());
                    }
                }
                pointMap.remove(key);
            } else {
                insertSkuList.add(stockPointSku);
            }
        }
        if (isUpdate) {
            for (Map.Entry<String, List<StockPointSkuVO>> map : pointMap.entrySet()) {
                // 修改需要删除掉没有的数据
                map.getValue().forEach(stockPointSkuVO -> deleteSkuIds.add(stockPointSkuVO.getStockPointSkuId()));
            }
        }
        if (CollectionUtil.isNotEmpty(insertSkuList)) {
            stockPointSkuMapper.batchSave(insertSkuList);
        }
        if (CollectionUtil.isNotEmpty(deleteSkuIds)) {
            stockPointSkuMapper.batchDeleteByStockPointSkuIdList(deleteSkuIds);
        }
    }

    @Override
    public List<StockPointSkuVO> listByPointId(Long stockPointId) {

        return stockPointSkuMapper.listByPointId(stockPointId);
    }

    @Override
    public void removeBySkuIdAndPointId(Long skuId, Long stockPointId) {
        stockPointSkuMapper.removeBySkuIdAndPointId(skuId, stockPointId);
    }

    @Override
    public List<StockPointSkuVO> listPointBySkuIds(List<Long> skuIds) {
        if (CollUtil.isEmpty(skuIds)) {
            return Collections.emptyList();
        }
        return stockPointSkuMapper.listPointBySkuIds(skuIds);
    }

    @Override
    public void updateStockMode(Long stockPointId, Integer stockMode) {
        stockPointSkuMapper.updateStockMode(stockPointId, stockMode);
    }

    @Override
    public List<StockPointSku> filtePoint(List<StockPointSku> stockPointSkuList) {
        List<StockPointSku> resultList = new ArrayList<>(stockPointSkuList.size());
        Long shopId = stockPointSkuList.get(0).getShopId();
        Long defaultId = warehouseMapper.getDefaultWarehouseIdByShopId(shopId, SysTypeEnum.MULTISHOP.value()).getWarehouseId();
        // 获取所有仓库
        List<WarehouseVO> warehouseList = warehouseMapper.listWarehouseByShopId(shopId, SysTypeEnum.MULTISHOP.value());
        Map<Long, WarehouseVO> warehouseDbMap = warehouseList.stream().collect(Collectors.toMap(WarehouseVO::getWarehouseId, s -> s));
        // 获取所有还存在的门店
        List<Long> stationIds = stockPointSkuList.stream().filter(stockPointSkuDTO -> stockPointSkuDTO.getStockPointType() == StockPointType.STATION.getValue()).map(StockPointSku::getStockPointId).toList();
        List<StationVO> stationVOS = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(stationIds)) {
            stationVOS = BeanUtil.mapAsList(stationMapper.selectList(new LambdaQueryWrapper<>(Station.class)
                    .in(Station::getStationId, stationIds)
                    .ne(Station::getStatus, -1)), StationVO.class);
        }
        Map<Long, StationVO> stationDbMap = stationVOS.stream().collect(Collectors.toMap(StationVO::getStationId, s -> s));

        Map<Long, List<StockPointSku>> skuStockPointMap = stockPointSkuList.stream().collect(Collectors.groupingBy(StockPointSku::getSkuId));
        for (Map.Entry<Long, List<StockPointSku>> map : skuStockPointMap.entrySet()) {
            List<Long> stockPointIds = map.getValue().stream().map(StockPointSku::getStockPointId).collect(Collectors.toList());
            // 先判断有没有默认仓库，没有就添加
            if (!stockPointIds.contains(defaultId)) {
                StockPointSku stockPointSku = new StockPointSku(defaultId, StockPointType.WAREHOUSE.getValue(), map.getValue().get(0).getProdId() , map.getKey(), map.getValue().get(0).getStatus(), 0, null);
                stockPointSku.setStock(0);
                resultList.add(stockPointSku);
            }
            Map<Integer, List<StockPointSku>> listMap = map.getValue().stream().collect(Collectors.groupingBy(StockPointSku::getStockPointType));
            int warehouseStock = 0;
            int stationStock = 0;
            // 1、过滤仓库集合
            if (listMap.containsKey(StockPointType.WAREHOUSE.getValue())) {
                List<StockPointSku> warehousePointList = listMap.get(StockPointType.WAREHOUSE.getValue());
                for (StockPointSku warehousePoint : warehousePointList) {
                    if (warehouseDbMap.containsKey(warehousePoint.getStockPointId())) {
                        resultList.add(warehousePoint);
                    } else {
                        // 没有的就将仓库库存补充到默认仓库
                        warehouseStock += warehousePoint.getStock();
                    }
                }
            }
            // 2、过滤门店集合
            if (listMap.containsKey(StockPointType.STATION.getValue())) {
                List<StockPointSku> stationList = listMap.get(StockPointType.STATION.getValue());
                for (StockPointSku stationPoint : stationList) {
                    if (stationDbMap.containsKey(stationPoint.getStockPointId())) {
                        StationVO stationVO = stationDbMap.get(stationPoint.getStockPointId());
                        if (stationVO.getStockMode().equals(StockModeEnum.SINGLE_STOCK.value())) {
                            resultList.add(stationPoint);
                        } else {
                            stationStock += stationPoint.getStock();
                        }
                    } else {
                        // 没有的就将仓库库存补充到默认仓库
                        stationStock += stationPoint.getStock();
                    }
                }
            }
            // 3、累加门店和仓库库存
            for (StockPointSku stockPointSku : resultList) {
                if (stockPointSku.getType() == 0 && stockPointSku.getSkuId().equals(map.getKey())){
                    stockPointSku.setStock(stockPointSku.getStock() + stationStock + warehouseStock);
                }
            }
        }
        resultList = resultList.stream().filter(stockPointSkuDTO -> stockPointSkuDTO.getStock() != 0).collect(Collectors.toList());
        return resultList;
    }

    @Override
    public List<StockPointSkuVO> listStockPointSku(StockPointSkuDTO stockPointSkuDTO) {
        return stockPointSkuMapper.listStockPointSku(stockPointSkuDTO);
    }

    @Override
    public List<Long> checkStockPointContainSku(List<Long> stockPointIds, List<Long> skuIds) {
        StockPointSkuDTO stockPointSkuDTO = new StockPointSkuDTO();
        stockPointSkuDTO.setStockPointIds(stockPointIds);
        List<StockPointSkuVO> stockPointSkus = stockPointSkuMapper.listStockPointSku(stockPointSkuDTO);
        if (CollectionUtils.isEmpty(stockPointSkus)) {
            return new ArrayList<>();
        }
        // 获取库存点含有的skuId
        List<Long> containSkuIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        Set<Long> dbSkuIds = stockPointSkus.stream().map(StockPointSkuVO::getSkuId).collect(Collectors.toSet());
        for (Long skuId : skuIds) {
            if (!dbSkuIds.contains(skuId)) {
                continue;
            }
            containSkuIds.add(skuId);
        }
        return containSkuIds;
    }

    @Override
    public void updateStockPointSkuRelate(List<Long> stockPointIds, List<Long> skuIds) {
        // 查询关联数据
        StockPointSkuDTO stockPointSkuDTO = new StockPointSkuDTO();
        stockPointSkuDTO.setStockPointIds(stockPointIds);
        stockPointSkuDTO.setSkuIds(skuIds);
        List<StockPointSkuVO> stockPointSkus = stockPointSkuMapper.listStockPointSku(stockPointSkuDTO);
        if (CollectionUtils.isEmpty(stockPointSkus)) {
            return;
        }
        // 查询库存
        List<SkuStockVO> skuStocks = new ArrayList<>(stockPointSkus.size());
        for (StockPointSkuVO stockPointSkuVO : stockPointSkus) {
            skuStocks.add(new SkuStockVO(stockPointSkuVO.getSkuId(), stockPointSkuVO.getStockPointId()));
        }
        Map<String, SkuStockVO> stockMap = stockManager.mapSkuStockBySkuStocks(skuStocks);
        // 非默认仓库，且库存不存在 or 库存为0，删除关联数据
        List<Long> deleteData = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (StockPointSkuVO stockPointSkuVO : stockPointSkus) {
            if (Objects.equals(stockPointSkuVO.getType(), 0)) {
                continue;
            }
            SkuStockVO skuStockVO = stockMap.get(StockUtil.skuPointKey(stockPointSkuVO.getSkuId(), stockPointSkuVO.getStockPointId()));
            if (Objects.isNull(skuStockVO)
                    || Objects.equals(skuStockVO.getStock(), 0)) {
                deleteData.add(stockPointSkuVO.getStockPointSkuId());
            }
        }
        if (!CollectionUtils.isEmpty(deleteData)) {
            stockPointSkuMapper.deleteByIds(deleteData);
        }
    }
}
